package com.woniuxy.charin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.charin.enumeration.*;
import com.woniuxy.charin.mapper.EventDisposeMapper;
import com.woniuxy.charin.mapper.EventMapper;
import com.woniuxy.charin.mapper.FormMapper;
import com.woniuxy.charin.model.entity.*;
import com.woniuxy.charin.model.request.EventRequest;
import com.woniuxy.charin.model.vo.EventDetailVo;
import com.woniuxy.charin.service.ChargingPileService;
import com.woniuxy.charin.service.EventService;
import com.woniuxy.charin.service.StationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author WH
 * @description 针对表【event】的数据库操作Service实现
 * @createDate 2024-12-25 10:30:20
 */
@Service
public class EventServiceImpl extends ServiceImpl<EventMapper, Event>
        implements EventService {
    @Autowired
    EventMapper eventMapper;
    @Autowired
    EventDisposeMapper eventDisposeMapper;
    @Autowired
    FormMapper formMapper;
    @Autowired
    ChargingPileService chargingPileService;
    @Autowired
    StationService stationService;

    //故障相关操作====================================================
    @Override
    public Page<EventDetailVo> pageFault(Integer pageNum, Integer pageSize, List<Integer> chargingPileIds, Date startDate, Date endDate) {
        endDate = addOneDay(endDate);
        Page<EventDetailVo> eventVoPage = pageEventByType(pageNum, pageSize, EventType.FAULT.getKey(),chargingPileIds, startDate, endDate);
        return eventVoPage;
    }

    @Override
    public void editFault(EventRequest request) {
        //因为可能涉及到修改充电桩id，所以修改前需要判断（1、id未修改：根据id查找出自己的对象，放行；2、id被修改，根据id查找出其他对象，如果存在则不修改，报错）
        Event findEvent = eventMapper.selectOne(Wrappers.lambdaQuery(Event.class)
                .eq(Event::getEventType, EventType.FAULT.getKey())
                .eq(Event::getChargingPileId, request.getChargingPileId())
                .in(Event::getCurrentStatus, EventStatus.PENDING.getKey(), EventStatus.PROCESSING.getKey())
        );
        if(findEvent!=null){
            Assert.error(findEvent.getId() != request.getId(), EventCode.CHARGINGPILES_FAULT_EXIST);
        }

        //获取数据库中Event对象，修改相应的值
        Event dbEvent = eventMapper.selectById(request.getId());
        dbEvent.setChargingPileId(request.getChargingPileId());
        dbEvent.setDescription(request.getDescription());
        dbEvent.setPriority(request.getPriority());
        dbEvent.setLocation(request.getLocation());
        dbEvent.setContacts(request.getContacts());
        dbEvent.setContactNumber(request.getContactNumber());
        eventMapper.updateById(dbEvent);

        System.out.println("编辑故障成功");
    }

    @Override
    public void addFault(Event event) {
        //进行新增隐患前的判断，例：在 处理中或待处理 时间内，同一个充电桩故障记录唯一。
        List<Event> dbEvents = eventMapper.selectList(Wrappers.lambdaQuery(Event.class)
                .eq(Event::getEventType, EventType.FAULT.getKey())
                .eq(Event::getChargingPileId, event.getChargingPileId())
                .in(Event::getCurrentStatus, EventStatus.PENDING.getKey(), EventStatus.PROCESSING.getKey())
        );
        Assert.error(!dbEvents.isEmpty(), EventCode.CHARGINGPILES_FAULT_EXIST);
        //新增隐患
        eventMapper.insert(event);
        System.out.println("新增故障成功");
    }

    //隐患相关操作====================================================
    @Override
    public Page<EventDetailVo> pageRisk(Integer pageNum, Integer pageSize, List<Integer> chargingPileIds, Date startDate, Date endDate) {
        endDate = addOneDay(endDate);
        Page<EventDetailVo> eventVoPage = pageEventByType(pageNum, pageSize, EventType.RISK.getKey(),chargingPileIds, startDate, endDate);
        return eventVoPage;
    }

    //修改隐患信息，只能在待处理、处理中进行修改
    @Override
    public void editRisk(EventRequest request) {
        //因为可能涉及到修改充电桩id，所以修改前需要判断（1、id未修改：根据id查找出自己的对象，放行；2、id被修改，根据id查找出其他对象，如果存在则不修改，报错）
        Event findEvent = eventMapper.selectOne(Wrappers.lambdaQuery(Event.class)
                .eq(Event::getEventType, EventType.RISK.getKey())
                .eq(Event::getChargingPileId, request.getChargingPileId())
                .in(Event::getCurrentStatus, EventStatus.PENDING.getKey(), EventStatus.PROCESSING.getKey())
        );
        if(findEvent!=null){
            Assert.error(findEvent.getId() != request.getId(), EventCode.CHARGINGPILES_RISK_EXIST);
        }

        //获取数据库中Event对象，修改相应的值
        Event dbEvent = eventMapper.selectById(request.getId());
        dbEvent.setChargingPileId(request.getChargingPileId());
        dbEvent.setDescription(request.getDescription());
        dbEvent.setPriority(request.getPriority());
        dbEvent.setLocation(request.getLocation());
        dbEvent.setContacts(request.getContacts());
        dbEvent.setContactNumber(request.getContactNumber());
        eventMapper.updateById(dbEvent);

        System.out.println("编辑隐患成功");
    }

    @Override
    public void retracteRisk(Long[] eventIds, String returnCause) {
        for (Long eventId : eventIds) {
            //事件表相关（修改事件状态）
            Event event = eventMapper.selectById(eventId);
            event.setCurrentStatus(EventStatus.RETRACTED.getKey());
            event.setReturnCause(returnCause);
            eventMapper.updateById(event);

            //如果事件类型为故障，则将充电桩状态改回空闲中（修改充电桩状态）
            if(event.getEventType()==EventType.FAULT.getKey()){
                chargingPileService.offlineChargingPile(Math.toIntExact(event.getChargingPileId()));
            }

            //处理表相关（只修改与事件相关的一条当前处理记录）
            if (event.getCurrentProcessorsId() != null) {
                EventDispose eventDispose = eventDisposeMapper.selectOne(Wrappers.lambdaQuery(EventDispose.class)
                        .eq(EventDispose::getEventId, eventId)
                        .eq(EventDispose::getProcessorsId, event.getCurrentProcessorsId())
                        .eq(EventDispose::getStatus, EventDisposeStatus.PROCESSING.getKey()));
                eventDispose.setStatus(EventDisposeStatus.RETRACTED.getKey());
                eventDisposeMapper.updateById(eventDispose);
                //更改form表中数据（只有指派了处理人，form表才会有数据）
                //updateFormStatus(Math.toIntExact(eventId),event.getEventType(), Math.toIntExact(event.getCurrentProcessorsId()),"已撤销");
            }
        }
        System.out.println("撤销隐患成功");
    }

    @Override
    public EventDetailVo getRiskDetail(Integer riskId) {
        //获取当前事件对应的事件对象
        Event event = eventMapper.selectById(riskId);
        // 查询充电桩信息
        ChargingPile chargingPile = chargingPileService.getChargingPileById(Math.toIntExact(event.getChargingPileId()));
        Station station = stationService.getById(chargingPile.getStationId()); // 查询充电站信息
        String stationName = station.getStationName();
        String pileCode = chargingPile.getPileCode();
        String address = station.getAddress();
        //赋值给event
        event.setStationName(stationName);
        event.setPileCode(pileCode);
        event.setAddress(address);
        //为EventDetailVo对象赋值
        EventDetailVo detailVo = new EventDetailVo();
        detailVo.setEvent(event);
        //判断是否存在处理人
        if (event.getCurrentProcessorsId() != null) {
            //构造条件选择器（用于查找出当前隐患对应的当前处理记录）
            LambdaQueryWrapper<EventDispose> eq = Wrappers.lambdaQuery(EventDispose.class)
                    .eq(EventDispose::getEventId, event.getId())
                    .eq(EventDispose::getProcessorsId, event.getCurrentProcessorsId())
                    .ne(EventDispose::getStatus, EventDisposeStatus.REFERRED.getKey());
            EventDispose eventDispose = eventDisposeMapper.selectOne(eq);
            detailVo.setEventDispose(eventDispose);
        }
        return detailVo;
    }

    @Override
    public void addRisk(Event event) {
        //进行新增隐患前的判断，例：在 处理中或待处理 时间内，同一个充电桩隐患记录唯一。
        List<Event> dbEvents = eventMapper.selectList(Wrappers.lambdaQuery(Event.class)
                .eq(Event::getEventType, EventType.RISK.getKey())
                .eq(Event::getChargingPileId, event.getChargingPileId())
                .in(Event::getCurrentStatus, EventStatus.PENDING.getKey(), EventStatus.PROCESSING.getKey())
        );
        Assert.error(!dbEvents.isEmpty(), EventCode.CHARGINGPILES_RISK_EXIST);
        //新增隐患
        eventMapper.insert(event);
        System.out.println("新增隐患成功");
    }

    //用于事件管理界面，查找所有事件
    private Page<EventDetailVo> pageEventByType(Integer pageNum, Integer pageSize, Integer type, List<Integer> chargingPileIds, Date startDate, Date endDate) {
        //创建隐患分页对象
        Page<Event> eventPage = new Page<>(pageNum, pageSize);
        //构建条件选择器
        LambdaQueryWrapper<Event> queryWrapper = Wrappers.lambdaQuery(Event.class)
                .eq(Event::getEventType, type)
                .orderByDesc(Event::getCreated);
        // 如果startDate和endDate都不为null，则添加between条件
        if (startDate != null && endDate != null) {
            queryWrapper.between(Event::getCreated, startDate, endDate);
        }
        // 如果chargingPileIds不为null，则添加 in 条件
        if(chargingPileIds!=null){
            queryWrapper.in(Event::getChargingPileId,chargingPileIds);
        }
        //开始查找，查找结果放入隐患分页对象
        eventMapper.selectPage(eventPage, queryWrapper);

        //创建EventDetailVo集合，为后续将Event转化为EventDetailVo，做准备
        List<EventDetailVo> eventDetailVos = new ArrayList<>();
        //获取隐患分页对象中原始查找结果
        List<Event> records = eventPage.getRecords();
        //遍历原始查找结果，并开始转换
        records.forEach(record -> {
            // 查询充电桩信息
            ChargingPile chargingPile = chargingPileService.getChargingPileById(Math.toIntExact(record.getChargingPileId()));
            Station station = stationService.getById(chargingPile.getStationId()); // 查询充电站信息
            String stationName = station.getStationName();
            String pileCode = chargingPile.getPileCode();
            String address = station.getAddress();
            //赋值给record
            record.setStationName(stationName);
            record.setPileCode(pileCode);
            record.setAddress(address);
            //创建空EventDetailVo对象
            EventDetailVo detailVo = new EventDetailVo();
            //判断是否存在处理人
            if (record.getCurrentProcessorsId() != null) {
                //构造条件选择器（用于查找出当前隐患对应的当前处理记录）
                LambdaQueryWrapper<EventDispose> eq = Wrappers.lambdaQuery(EventDispose.class)
                        .eq(EventDispose::getEventId, record.getId())
                        .eq(EventDispose::getProcessorsId, record.getCurrentProcessorsId())
                        .ne(EventDispose::getStatus, EventDisposeStatus.REFERRED.getKey());
                EventDispose eventDispose = eventDisposeMapper.selectOne(eq);
                detailVo.setEventDispose(eventDispose);
            }
            detailVo.setEvent(record);
            eventDetailVos.add(detailVo);
        });
        //仿造隐患分页对象，创建EventDetailVo分页对象
        Page<EventDetailVo> eventVoPage = new Page<>(pageNum, pageSize, eventPage.getTotal());
        eventVoPage.setRecords(eventDetailVos);
        return eventVoPage;
    }

    // 用于将Date对象增加一天
    private Date addOneDay(Date date) {
        if (date == null) {
            return null;
        }
        // 将Date转换为Instant
        Instant instant = date.toInstant();
        // 将Instant转换为ZonedDateTime以便进行日期加减
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
        // 增加一天
        ZonedDateTime newZonedDateTime = zonedDateTime.plusDays(1);
        // 将新的ZonedDateTime转换回Instant
        Instant newInstant = newZonedDateTime.toInstant();
        // 将Instant转换回Date
        Date newDate = Date.from(newInstant);
        return newDate;
    }

//    //添加一条数据到form表中
//    private void addForm(Integer eventId, Integer eventType, Integer userId) {
//        Form form = new Form();
//        form.setFormId(eventId);
//        String modelName = eventType == EventType.RISK.getKey() ? "隐患管理" : "故障管理";
//        form.setModelName(modelName);
//        form.setUserId(userId);
//        form.setStatus("待审核");
//        formMapper.insert(form);
//    }
//
//    //删除form表中数据
//    private void updateFormStatus(Integer eventId, Integer eventType, Integer userId,String status){
//        Form form = formMapper.selectOne(Wrappers.lambdaQuery(Form.class)
//                .eq(Form::getFormId, eventId)
//                .eq(Form::getModelName, eventType == EventType.RISK.getKey() ? "隐患管理" : "故障管理")
//                .eq(Form::getUserId, userId)
//                .eq(Form::getStatus, "待审核"));
//        if(form!=null){
//            form.setStatus(status);
//            formMapper.updateById(form);
//        }
//    }
}




